package com.annotation.validator;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.annotation.Validations;

@Service
@Scope("prototype")
public class ExecutionValidator {
	private Logger log = LoggerFactory.getLogger(ExecutionValidator.class);
	private List<Validator> validators = new ArrayList<Validator>();

	public void validate(Class clz, String method) {
		Method[] ms = clz.getDeclaredMethods();
		for (Method m : ms) {
			String mName = m.getName();
			if (StringUtils.equals(mName, method)) {
				exceValidate(m);
			}
		}
		for (Validator v : validators) {
			v.validate();
		}
	}

	private List<Method> continueMethods(Method[] method) {
		List<Method> methods = new ArrayList<Method>();
		for (int i = 0; i < method.length; i++) {
			if ("equals".equals(method[i].getName())) {
				ArrayUtils.remove(method, i);
			} else if ("toString".equals(method[i].getName())) {
				ArrayUtils.remove(method, i);
			} else if ("hashCode".equals(method[i].getName())) {
				ArrayUtils.remove(method, i);
			} else if ("annotationType".equals(method[i].getName())) {
				ArrayUtils.remove(method, i);
			} else {
				methods.add(method[i]);
			}
		}
		return methods;
	}

	private void exceValidate(Method m) {
		if (m.isAnnotationPresent(Validations.class)) {
			Validations v = m.getAnnotation(Validations.class);
			Method[] ms = v.getClass().getDeclaredMethods();
			List<Method> methods = continueMethods(ms);
			for (Method method : methods) {
				Object[] validateOvjAnnotaion = null;
				try {
					validateOvjAnnotaion = (Object[]) method.invoke(v);
				} catch (Exception e) {
					log.error("反射 Validations注解类里面所有方法异常", e);
				}
				if (validateOvjAnnotaion.length != 0)
					dynaminValue(validateOvjAnnotaion);
			}

		}
	}

	private void dynaminValue(Object[] obj) {
		for (Object object : obj) {
			Map mData = new HashMap();
			Method[] ms = object.getClass().getDeclaredMethods();
			List<Method> methods = continueMethods(ms);
			for (Method method : methods) {
				Object o = null;
				try {
					o = method.invoke(object);
					mData.put(method.getName(), o);
				} catch (Exception e) {
					log.error("根据方法名获取方法返回值异常", e);
				}
			}
			String com = "com.annotation.validator.";
			String className = object.toString().replace(
					"@com.annotation.", com);
			int wait = className.indexOf("(");
			className = className.substring(0, wait);
			Validator validate = null;
			try {
				validate = (Validator) Class.forName(className).newInstance();
			} catch (Exception e) {
				log.error("根据累名称获取实例异常 " + className, e);
			}
			Field[] classFields = validate.getClass().getDeclaredFields();
			Field[] superFields = validate.getClass().getSuperclass()
					.getDeclaredFields();
			Field[] fields = (Field[]) ArrayUtils.addAll(classFields,
					superFields);
			for (Field field : fields) {
				field.setAccessible(true);
				String fieldName = field.getName();
				if (mData.containsKey(fieldName)) {
					try {
						field.set(validate, mData.get(fieldName));
					} catch (Exception e) {
						log.error("私有属性复值异常 " + fieldName, e);
					}
				}
			}
			validators.add(validate);
		}
	}
}
